package com.back.demo.service;

import com.back.demo.common.Role;
import com.back.demo.controller.myVO.basicVO.ClassVO;
import com.back.demo.controller.myVO.basicVO.MajorVO;
import com.back.demo.controller.myVO.basicVO.MentorVO;
import com.back.demo.common.Permission;
import com.back.demo.exception.GlobalException;
import com.back.demo.mapper.BasicMapper;
import com.back.demo.common.User;
import com.back.demo.mapper.myDO.basicDO.ClassDO;
import com.back.demo.mapper.myDO.basicDO.MajorDO;
import com.back.demo.mapper.myDO.basicDO.MentorDO;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.back.demo.controller.myVO.errorBeanEnum.BasicResponseBeanEnum.USER_ERROR;

@Slf4j
@org.springframework.stereotype.Service
public class BasicService {
    @Autowired
    private BasicMapper basicMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private final ObjectMapper objectMapper = new ObjectMapper();

    // basic
    // basic
    // basic
    public User findUserByUsername(String username) throws GlobalException {
        String userJson = redisTemplate.opsForValue().get("user(username):" + username);
        if (userJson != null) {
            try {
                return objectMapper.readValue(userJson, new TypeReference<User>() {
                });
            } catch (JsonProcessingException e) {
                log.warn("从Redis中解析用户名{}对应的信息时出现异常！", username);
                redisTemplate.delete("user(username):" + username);
//                throw new RuntimeException("123456");
            }
        }
        User user = basicMapper.selectUserByUsername(username);
        if (user == null) {
            log.warn("不存在用户名为{}的用户", username);
            throw new GlobalException(USER_ERROR);
        }
        try {
            userJson = objectMapper.writeValueAsString(user);
            redisTemplate.opsForValue().set(("user(username):" + username), userJson, 60, TimeUnit.SECONDS);
        } catch (JsonProcessingException e) {
            log.warn("向Redis中存储用户{}对应的信息时出现异常！", username);
        }
        return user;
    }

    public ArrayList<Role> findRoleByUser(User user) throws GlobalException {
/*        String roleJson = redisTemplate.opsForValue().get("role(username):" + user.getUsername());
        if (roleJson != null) {
            try {
                return objectMapper.readValue(roleJson, new TypeReference<ArrayList<Role>>() {
                });
            } catch (JsonProcessingException e) {
                log.warn("从Redis中解析用户名为{}对应的角色信息时出现异常！", user.getUsername());
                redisTemplate.delete("role(username):" + user.getUsername());
            }
        }*/
        ArrayList<Role> roleList = basicMapper.selectRoleByUserId(user.getUserId());
        if (null == roleList || roleList.isEmpty()) {
            log.error("用户名为{}的用户角色信息错误", user.getUsername());
            throw new GlobalException(USER_ERROR);
        }
/*        try {
            roleJson = objectMapper.writeValueAsString(roleList);
            redisTemplate.opsForValue().set(("role(username):" + user.getUsername()), roleJson, 30, TimeUnit.SECONDS);
        } catch (JsonProcessingException e) {
            log.warn("向Redis中存储用户名{}对应的角色信息时出现异常！", user.getUsername());
        }*/
        return roleList;
    }

    public ArrayList<Integer> findRoleIdByUsername(String username) throws GlobalException {
        String roleIdJson = redisTemplate.opsForValue().get("roleId(username):" + username);
        if (roleIdJson != null) {
            try {
                return objectMapper.readValue(roleIdJson, new TypeReference<ArrayList<Integer>>() {
                });
            } catch (JsonProcessingException e) {
                log.warn("从Redis中解析用户名{}对应的角色ID列表时出现异常！", username);
                redisTemplate.delete("roleId(username):" + username);
            }
        }
        User user = findUserByUsername(username);
        ArrayList<Role> roleList = findRoleByUser(user);
        ArrayList<Integer> roleIdList = new ArrayList<>();
        for (Role role : roleList) {
            roleIdList.add(role.getRoleId());
        }
        try {
            roleIdJson = objectMapper.writeValueAsString(roleIdList);
            redisTemplate.opsForValue().set(("roleId(username):" + user.getUsername()), roleIdJson, 10, TimeUnit.MINUTES);
        } catch (JsonProcessingException e) {
            log.warn("向Redis中存储用户名{}对应的角色ID列表时出现异常！", user.getUsername());
        }
        return roleIdList;
    }

    public ArrayList<Permission> findPermissionByUsername(String username) throws GlobalException {
        ArrayList<Integer> roleIdList = findRoleIdByUsername(username);
        if (1 == roleIdList.size()) {
            Integer roleId = roleIdList.get(0);
            String permissionJson = redisTemplate.opsForValue().get("permission(roleId):" + roleId.toString());
            if (null != permissionJson) {
                try {
                    return objectMapper.readValue(permissionJson, new TypeReference<ArrayList<Permission>>() {
                    });
                } catch (JsonProcessingException e) {
                    log.warn("从Redis中解析角色ID{}对应的权限时出现异常！", roleId);
                    redisTemplate.delete("permission(roleId):" + roleId);
                }
            } else {
                ArrayList<Permission> permissionList = basicMapper.selectPermissionByUsername(username);
                try {
                    permissionJson = objectMapper.writeValueAsString(permissionList);
                    redisTemplate.opsForValue().set("permission(roleId):" + roleId, permissionJson, 1, TimeUnit.DAYS);
                    return permissionList;
                } catch (JsonProcessingException e) {
                    log.warn("向Redis中存储角色ID{}对应的权限时出现异常！", roleId);
                }
            }
        }
        return basicMapper.selectPermissionByUsername(username);
    }

    public String getName(String username) {
        User user = findUserByUsername(username);
        // 如果角色数组为空，则会直接抛出异常，这里不需要处理了
        Integer roleId = findRoleIdByUsername(username).get(0);
        Integer userId = user.getUserId();
/*        if (roleId == null) {
            return "佚名";
        }*/
        String name = redisTemplate.opsForValue().get("name(username):" + username);
        if (null == name) {
            switch (roleId) {
                case 1:
                    name = basicMapper.selectStuName(userId);
                    break;
                case 2:
                    name = basicMapper.selectJudgeName(userId);
                    break;
                case 3:
                    name = basicMapper.selectAdminName(userId);
                    break;
                default:
                    name = "佚名";
                    break;
            }
            redisTemplate.opsForValue().set("name(username):" + username, name, 10, TimeUnit.MINUTES);
        }
        return name;
    }

    public void changePassword(String username, String newPassword) {
        basicMapper.changePassword(username, newPassword);
        redisTemplate.delete(("user(username):" + username));
    }
    // basic
    // basic
    // basic

    // major
    // major
    // major
    public ArrayList<MajorVO> acquireMajor() {
        String majorVOListJson = redisTemplate.opsForValue().get("majorVOListJson");
        if (majorVOListJson != null) {
            try {
                return objectMapper.readValue(majorVOListJson, new TypeReference<ArrayList<MajorVO>>() {
                });
            } catch (JsonProcessingException e) {
                log.error("从Redis中解析专业表时出错！");
                redisTemplate.delete("majorVOListJson");
            }
        }

        ArrayList<MajorDO> listDO = basicMapper.selectMajor();
        ArrayList<MajorVO> listVO = new ArrayList<>();
        for (MajorDO majorDO : listDO) {
            MajorVO majorVO = new MajorVO();
            majorVO.setMajorId(majorDO.getMajorId());
            majorVO.setMajorCode(majorDO.getMajorCode());
            majorVO.setMajorName(majorDO.getMajorName());
            listVO.add(majorVO);
            try {
                String majorVOJson = objectMapper.writeValueAsString(majorVO);
                redisTemplate.opsForValue().set("majorVO(majorId):" + majorVO.getMajorId(), majorVOJson);
            } catch (JsonProcessingException e) {
                log.error("存储ID为{}的专业信息到Redis时出错！", majorVO.getMajorId());
            }
        }
        try {
            majorVOListJson = objectMapper.writeValueAsString(listVO);
            redisTemplate.opsForValue().set("majorVOListJson", majorVOListJson);
        } catch (JsonProcessingException e) {
            log.error("存储专业表到Redis时出错！");
        }
        return listVO;

    }

    public MajorVO getMajorByMajorId(Integer majorId) throws IllegalArgumentException {
        String majorVOJson = redisTemplate.opsForValue().get("majorVO(majorId):" + majorId);
        if (null != majorVOJson) {
            try {
                return objectMapper.readValue(majorVOJson, new TypeReference<MajorVO>() {
                });
            } catch (JsonProcessingException e) {
                log.error("从Redis中解析专业VO时出错！");
                redisTemplate.delete("majorVO(majorId):" + majorId);
            }
        }
        MajorDO majorDO = basicMapper.selectMajorByMajorId(majorId);
        MajorVO majorVO = new MajorVO();
        majorVO.setMajorId(majorDO.getMajorId());
        majorVO.setMajorCode(majorDO.getMajorCode());
        majorVO.setMajorName(majorDO.getMajorName());
        try {
            majorVOJson = objectMapper.writeValueAsString(majorVO);
            redisTemplate.opsForValue().set("majorVO(majorId):" + majorId, majorVOJson);
        } catch (JsonProcessingException e) {
            log.error("存储专业VO到Redis时出错！");
        }
        return majorVO;
    }

    public MajorDO getMajorByMajorCode(String majorCode) throws IllegalArgumentException {
        String majorDOJson = redisTemplate.opsForValue().get("majorDO(majorCode):" + majorCode);
        if (null != majorDOJson) {
            try {
                return objectMapper.readValue(majorDOJson, new TypeReference<MajorDO>() {
                });
            } catch (JsonProcessingException e) {
                log.error("从Redis中解析专业DO时出错！");
                redisTemplate.delete("majorDO(majorCode):" + majorCode);
            }
        }
        MajorDO majorDO = basicMapper.selectMajorByMajorCode(majorCode);
        try {
            majorDOJson = objectMapper.writeValueAsString(majorDO);
            redisTemplate.opsForValue().set("majorDO(majorCode):" + majorCode, majorDOJson, 30, TimeUnit.SECONDS);
        } catch (JsonProcessingException e) {
            log.error("存储专业DO到Redis时出错！");
        }
        return majorDO;
    }
    // major
    // major
    // major

    // class
    // class
    // class
    public ArrayList<ClassVO> acquireClass() {
        String classVOListJson = redisTemplate.opsForValue().get("classVOListJson");
        if (classVOListJson != null) {
            try {
                return objectMapper.readValue(classVOListJson, new TypeReference<ArrayList<ClassVO>>() {
                });
            } catch (JsonProcessingException e) {
                log.error("从Redis中解析学苑表时出错！");
                redisTemplate.delete("classVOListJson");
            }
        }

        ArrayList<ClassDO> listDO = basicMapper.selectClass();
        ArrayList<ClassVO> listVO = new ArrayList<>();
        for (ClassDO classDO : listDO) {
            ClassVO classVO = new ClassVO();
            classVO.setClassId(classDO.getClassId());
            classVO.setClassOrder(classDO.getClassOrder());
            classVO.setClassName(classDO.getClassName());
            listVO.add(classVO);
            try {
                String classVOJson = objectMapper.writeValueAsString(classVO);
                redisTemplate.opsForValue().set("classVO(classId):" + classVO.getClassId(), classVOJson);
            } catch (JsonProcessingException e) {
                log.error("存储ID为{}的学苑信息到Redis时出错！", classVO.getClassId());
            }
        }
        try {
            classVOListJson = objectMapper.writeValueAsString(listVO);
            redisTemplate.opsForValue().set("classVOListJson", classVOListJson);
        } catch (JsonProcessingException e) {
            log.error("存储学苑表到Redis时出错！");
        }
        return listVO;
    }

    public ClassVO getClassByClassId(Integer classId) throws IllegalArgumentException {
        String classVOJson = redisTemplate.opsForValue().get("classVO(classId):" + classId);
        if (null != classVOJson) {
            try {
                return objectMapper.readValue(classVOJson, new TypeReference<ClassVO>() {
                });
            } catch (JsonProcessingException e) {
                log.error("从Redis中解析学苑VO时出错！");
                redisTemplate.delete("classVO(classId):" + classId);
            }
        }

        ClassDO classDO = basicMapper.selectClassByClassId(classId);
        ClassVO classVO = new ClassVO();
        classVO.setClassId(classDO.getClassId());
        classVO.setClassOrder(classDO.getClassOrder());
        classVO.setClassName(classDO.getClassName());
        try {
            classVOJson = objectMapper.writeValueAsString(classVO);
            redisTemplate.opsForValue().set("classVO(classId):" + classId, classVOJson);
        } catch (JsonProcessingException e) {
            log.error("存储学苑VO到Redis时出错！");
        }

        return classVO;
    }
    // class
    // class
    // class

    // mentor
    // mentor
    // mentor
    public ArrayList<MentorVO> acquireMentor() {

        String mentorVOListJson = redisTemplate.opsForValue().get("mentorVOListJson");
        if (mentorVOListJson != null) {
            try {
                return objectMapper.readValue(mentorVOListJson, new TypeReference<ArrayList<MentorVO>>() {
                });
            } catch (JsonProcessingException e) {
                log.error("从Redis中解析导师表时出错！");
                redisTemplate.delete("mentorVOListJson");
            }
        }

        ArrayList<MentorDO> listDO = basicMapper.selectMentor();
        ArrayList<MentorVO> listVO = new ArrayList<>();
        for (MentorDO mentorDO : listDO) {
            MentorVO mentorVO = new MentorVO();
            mentorVO.setMentorId(mentorDO.getMentorId());
            mentorVO.setJobId(mentorDO.getJobId());
            mentorVO.setMentorName(mentorDO.getMentorName());
            listVO.add(mentorVO);
            try {
                String mentorVOJson = objectMapper.writeValueAsString(mentorVO);
                redisTemplate.opsForValue().set("mentorVO(mentorId):" + mentorVO.getMentorId(), mentorVOJson);
            } catch (JsonProcessingException e) {
                log.error("存储ID为{}的导师信息到Redis时出错！", mentorVO.getMentorId());
            }
        }
        try {
            mentorVOListJson = objectMapper.writeValueAsString(listVO);
            redisTemplate.opsForValue().set("mentorVOListJson", mentorVOListJson);
        } catch (JsonProcessingException e) {
            log.error("存储导师表到Redis时出错！");
        }
        return listVO;
    }

    public MentorVO getMentorByMentorId(Integer mentorId) throws IllegalArgumentException {
        String mentorVOJson = redisTemplate.opsForValue().get("mentorVO(mentorId):" + mentorId);
        if (null != mentorVOJson) {
            try {
                return objectMapper.readValue(mentorVOJson, new TypeReference<MentorVO>() {
                });
            } catch (JsonProcessingException e) {
                log.error("从Redis中解析导师VO时出错！");
                redisTemplate.delete("mentorVO(mentorId):" + mentorId);
            }
        }
        MentorDO mentorDO = basicMapper.selectMentorByMentorId(mentorId);
        MentorVO mentorVO = new MentorVO();
        mentorVO.setMentorId(mentorDO.getMentorId());
        mentorVO.setJobId(mentorDO.getJobId());
        mentorVO.setMentorName(mentorDO.getMentorName());
        try {
            mentorVOJson = objectMapper.writeValueAsString(mentorVO);
            redisTemplate.opsForValue().set("mentorVO(mentorId):" + mentorId, mentorVOJson);
        } catch (JsonProcessingException e) {
            log.error("存储导师VO到Redis时出错！");
        }
        return mentorVO;
    }

    public MentorDO getMentorByJobId(String jobId) throws IllegalArgumentException {
        String mentorDOJson = redisTemplate.opsForValue().get("mentorDO(jobId):" + jobId);
        if (null != mentorDOJson) {
            try {
                return objectMapper.readValue(mentorDOJson, new TypeReference<MentorDO>() {
                });
            } catch (JsonProcessingException e) {
                log.error("从Redis中解析导师DO时出错！");
                redisTemplate.delete("mentorDO(jobId):" + jobId);
            }
        }
        MentorDO mentorDO = basicMapper.selectMentorByJobId(jobId);
        try {
            mentorDOJson = objectMapper.writeValueAsString(mentorDO);
            redisTemplate.opsForValue().set("mentorDO(jobId):" + jobId, mentorDOJson, 30, TimeUnit.SECONDS);
        } catch (JsonProcessingException e) {
            log.error("存储导师DO到Redis时出错！");
        }
        return mentorDO;
    }
    // mentor
    // mentor
    // mentor

}
